﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ModBot.ConfigBuilder.Providers
{
    public class EventSettingsProvider
    {
        private ModBotSettingsProvider parentProvider;
        public List<EventSettingInstanceProvider> EventSettingInstances;

        #region Public Properties

        /// <summary>
        /// Gets the number of event options configured
        /// </summary>
        public int AECount { get; set; }

        /// <summary>
        /// Gets or sets the interval in seconds to check for events.
        /// </summary>
        public int AECheckTime { get; set; }

        /// <summary>
        /// Gets or sets the second custom emote triggered 
        /// event driven by scripts.
        /// Each AECustomX entry, if defined, must have a corresponding 
        /// script entry. For example, by defining AECustom1=greater bloodmoon healing  
        /// in the AdvEvent section, you would need a corresponding script defined.
        /// </summary>
        public string AECustom1 { get; set; }

        /// <summary>
        /// Gets or sets the second custom emote triggered 
        /// event driven by scripts.
        /// Each AECustomX entry, if defined, must have a corresponding 
        /// script entry. For example, by defining AECustom1=greater bloodmoon healing  
        /// in the AdvEvent section, you would need a corresponding script defined.
        /// </summary>
        public string AECustom2 { get; set; }

        /// <summary>
        /// Gets or sets the third custom emote triggered 
        /// event driven by scripts.
        /// Each AECustomX entry, if defined, must have a corresponding 
        /// script entry. For example, by defining AECustom1=greater bloodmoon healing  
        /// in the AdvEvent section, you would need a corresponding script defined.
        /// </summary>
        public string AECustom3 { get; set; }


        #endregion

        private EventSettingsProvider() { }
        public EventSettingsProvider(ModBotSettingsProvider parentProvider)
        {
            this.parentProvider = parentProvider;
            EventSettingInstances = new List<EventSettingInstanceProvider>();
        }

        public override string ToString()
        {
            #region Format String
            string formatString =
                "[AdvEvent]\r\n" +
                "AECount={0}\r\n" +
                "AECheckTime={1}\r\n" +
                "AECustom1={2}\r\n" +
                "AECustom2={3}\r\n" +
                "AECustom3={4}\r\n\r\n";


            #endregion


            string output = string.Format(formatString,
                AECount,
                AECheckTime,
                AECustom1,
                AECustom2,
                AECustom3);

            foreach (EventSettingInstanceProvider provider in this.EventSettingInstances)
            {
                output += provider.ToString();
            }


            return output;
        }

        public static EventSettingsProvider LoadFromINI(ModBotSettingsProvider settingsProvider, string filepath)
        {
            EventSettingsProvider provider = new EventSettingsProvider(settingsProvider);

            try
            {
                provider.AECount = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventSettings_Key_AECount), Defaults.Default_EventSettings_AECount);
                provider.AECheckTime = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventSettings_Key_AECheckTime), Defaults.Default_EventSettings_AECheckTime);
                provider.AECustom1 = IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventSettings_Key_AECustom1);
                provider.AECustom2 = IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventSettings_Key_AECustom2);
                provider.AECustom3 = IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventSettings_Key_AECustom3);


                provider.EventSettingInstances.Clear();
                for (int i = 0; i < provider.AECount; i++)
                {
                    EventSettingInstanceProvider instance = EventSettingInstanceProvider.LoadFromINI(provider, i + 1, filepath);
                    provider.EventSettingInstances.Add(instance);
                }


                if (provider.AECount != provider.EventSettingInstances.Count) provider.AECount = provider.EventSettingInstances.Count;

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return provider;
        }

        public static void SaveToIni(EventSettingsProvider provider, string filepath)
        {
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventSettings_Key_AECount, Convert.ToString(provider.AECount));
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventSettings_Key_AECheckTime, Convert.ToString(provider.AECheckTime));
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventSettings_Key_AECustom1, provider.AECustom1);
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventSettings_Key_AECustom1, provider.AECustom2);
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventSettings_Key_AECustom1, provider.AECustom3);


            for (int i = 0; i < provider.AECount; i++)
            {
                EventSettingInstanceProvider.SaveToIni(provider.EventSettingInstances[i], filepath);
            }
        }
    }

    public class EventSettingInstanceProvider
    {
        private EventSettingsProvider settingsProvider;
        /// <summary>
        /// Gets or sets the Gem number, alt, ability, item, script, or potionbelt reference to use
        /// for this event.
        /// </summary>
        public string AEGem { get; set; }

        /// <summary>
        /// Gets or sets the spell, item, alt, ability, or script name to reference with 
        /// this event.
        /// </summary>
        public string AESpell { get; set; }

        /// <summary>
        /// Gets or sets the bandolier set name to swap in before casting the event.
        /// Please see MQ2Bandolier and MQ2Cast for more information.
        /// </summary>
        public string AESpellFoci { get; set; }

        /// <summary>
        /// Gets or sets any spell extension percentage.
        /// </summary>
        public int AEDurMod { get; set; }

        /// <summary>
        /// Gets or sets the number of seconds to wait between
        /// casts of the event spell.
        /// </summary>
        public int AEDelay { get; set; }
        
        /// <summary>
        /// Gets or sets the minimum mana percentage to have before
        /// attempting the event.
        /// </summary>
        public int AEEventMinMana { get; set; }

        /// <summary>
        /// Gets or sets the minimum hp percentage to have before
        /// attempting the event.
        /// </summary>
        public int AEEventMinHP { get; set; }

        /// <summary>
        /// Gets or sets the minimum mana necessary to complete 
        /// the event.
        /// </summary>
        public int AEMinMana { get; set; }

        /// <summary>
        /// Gets or sets the maximum mana necessary to complete 
        /// the event.
        /// </summary>
        public int AEMaxMana { get; set; }

        /// <summary>
        /// Gets or sets the minimum hp necessary to complete
        /// the event.
        /// </summary>
        public int AEMinHP { get; set; }

        /// <summary>
        /// Gets or sets the maximum hp necessary to complete
        /// the event.
        /// </summary>
        public int AEMaxHP { get; set; }

        /// <summary>
        /// Gets or sets the class or target list for this event.
        /// </summary>
        public string AETarType { get; set; }

        /// <summary>
        /// Gets or sets the alias for the spell being cast. Note this alias
        /// must be unique and cannot contain spaces.
        /// </summary>
        public string AESpellAlias { get; set; }

        /// <summary>
        /// Gets or sets the channel to announce the event or, if left blank
        /// will not announce the event.
        /// </summary>
        public string AEAnnounce { get; set; }

        /// <summary>
        /// From WIKI : 
        /// AETarCnt - (Settings are *only* either 1 (on) or 0 (off).) 
        /// </summary>
        public Boolean AETarCnt { get; set; }        

        /// <summary>
        /// Gets or sets the event group index.
        /// </summary>
        public int Index { get; set; }

        private EventSettingInstanceProvider() { }

        public EventSettingInstanceProvider(EventSettingsProvider settingsProvider, int index)
        {
            this.settingsProvider = settingsProvider;
            this.Index = index;

            this.AEGem = Defaults.Default_EventInstance_AEGem;
            this.AESpell = Defaults.Default_EventInstance_AESpell;
            this.AESpellFoci = Defaults.Default_EventInstance_AESpellFoci;
            this.AEDurMod = Defaults.Default_EventInstance_AEDurMod;
            this.AEDelay = Defaults.Default_EventInstance_AEDelay;
            this.AEEventMinMana = Defaults.Default_EventInstance_AEEventMinMana;
            this.AEEventMinHP = Defaults.Default_EventInstance_AEEventMinHP;
            this.AEMinMana = Defaults.Default_EventInstance_AEMinMana;
            this.AEMaxMana = Defaults.Default_EventInstance_AEMaxMana;
            this.AEMinHP = Defaults.Default_EventInstance_AEMinHP;
            this.AEMaxHP = Defaults.Default_EventInstance_AEMaxHP;
            this.AETarType = Defaults.Default_EventInstance_AETarType;
            this.AESpellAlias = Defaults.Default_EventInstance_AESpellAlias;
            this.AEAnnounce = Defaults.Default_EventInstance_AEAnnounce;
            this.AETarCnt = Defaults.Default_EventInstance_AETarCnt;
        }

        public override string ToString()
        {
            #region Format String
            string formatString =
                SharedLib.CreateSubCommentBlock("Event Instance " + Index, SharedLib.NewLine, true) +
                "AEGem{0}={1}\r\n" +
                "AESpell{0}={2}\r\n" +
                "AESpellFoci{0}={3}\r\n" +
                "AEDurMod{0}={4}\r\n" +
                "AEDelay{0}={5}\r\n" +
                "AEEventMinMana{0}={6}\r\n" +
                "AEEventMinHP{0}={7}\r\n" +
                "AEMinMana{0}={8}\r\n" +
                "AEMaxMana{0}={9}\r\n" +
                "AEMinHP{0}={10}\r\n" +
                "AEMaxHP{0}={11}\r\n" +
                "AETarType{0}={12}\r\n" +
                "AESpellAlias{0}={13}\r\n" +
                "AEAnnounce{0}={14}\r\n" +
                "AETarCnt{0}={15}\r\n\r\n";

            #endregion


            string output = string.Format(formatString,
                Index,
                AEGem, 
                AESpell, 
                AESpellFoci, 
                AEDurMod, 
                AEDelay, 
                AEEventMinMana, 
                AEEventMinHP, 
                AEMinMana, 
                AEMaxMana, 
                AEMinHP, 
                AEMaxHP, 
                AETarType, 
                AESpellAlias, 
                AEAnnounce, 
                AETarCnt);

            return output;
        }

        public static EventSettingInstanceProvider LoadFromINI(EventSettingsProvider settingsProvider, int index, string filepath)
        {
            EventSettingInstanceProvider provider = new EventSettingInstanceProvider(settingsProvider, index);

            try
            {
                provider.AEGem = IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index);
                provider.AESpell = IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AESpell + provider.Index);
                provider.AESpellFoci = IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AESpellFoci + provider.Index);
                provider.AEDurMod = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEDurMod + provider.Index), Defaults.Default_EventInstance_AEDurMod);
                provider.AEDelay = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEDelay + provider.Index), Defaults.Default_EventInstance_AEDelay);
                provider.AEEventMinMana = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEEventMinMana + provider.Index), Defaults.Default_EventInstance_AEEventMinMana);
                provider.AEEventMinHP = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEEventMinHP + provider.Index), Defaults.Default_EventInstance_AEEventMinHP);
                provider.AEMinMana = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEMinMana + provider.Index), Defaults.Default_EventInstance_AEMinMana);
                provider.AEMaxMana = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEMaxMana + provider.Index), Defaults.Default_EventInstance_AEMaxMana);
                provider.AEMinHP = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEMinHP + provider.Index), Defaults.Default_EventInstance_AEMinHP);
                provider.AEMaxHP = SharedLib.ConvertToInt32(IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEMaxHP + provider.Index), Defaults.Default_EventInstance_AEMaxHP);
                provider.AETarType = IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AETarType + provider.Index);
                provider.AESpellAlias = IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AESpellAlias + provider.Index);
                provider.AEAnnounce = IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEAnnounce + provider.Index);
                provider.AETarCnt = SharedLib.ConvertToBoolean(IniFileProvider.ReadValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AETarCnt + provider.Index), Defaults.Default_EventInstance_AETarCnt);

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return provider;
        }

        public static void SaveToIni(EventSettingInstanceProvider provider, string filepath)
        {
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, Convert.ToString(provider.AEGem));            
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, Convert.ToString(provider.AESpell));
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, Convert.ToString(provider.AESpellFoci));
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, Convert.ToString(provider.AEDurMod));
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, Convert.ToString(provider.AEDelay));
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, Convert.ToString(provider.AEEventMinMana));
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, Convert.ToString(provider.AEEventMinHP));
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, Convert.ToString(provider.AEMinMana));
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, Convert.ToString(provider.AEMaxMana));
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, Convert.ToString(provider.AEMinHP));
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, Convert.ToString(provider.AEMaxHP));
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, Convert.ToString(provider.AETarType));
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, Convert.ToString(provider.AESpellAlias));
            IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, Convert.ToString(provider.AEAnnounce));

            // Special case here where Boolean translated to 0/1
            if (provider.AETarCnt)
            {
                IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, "1");
            }
            else
            {
                IniFileProvider.WriteValue(filepath, Keys.EventSettings_Section_Key, Keys.EventInstance_Key_AEGem + provider.Index, "0");
            }
        }
    }

}
